use slist::slist::{SListEntry, slist_append, slist_prepend, slist_free, slist_next, slist_nth_entry, slist_nth_data, slist_length, slist_remove_data, slist_sort, slist_remove_entry, slist_find_data, slist_to_array, SListCompareFunc, SListEqualFunc, SListIterator};

#[test]
fn test_slist_append() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());
    assert_eq!(slist_length(&list), 4);

    assert_eq!(slist_nth_data(&list, 0), Some(&variable1));
    assert_eq!(slist_nth_data(&list, 1), Some(&variable2));
    assert_eq!(slist_nth_data(&list, 2), Some(&variable3));
    assert_eq!(slist_nth_data(&list, 3), Some(&variable4));

    slist_free(&mut list);
}

#[test]
fn test_slist_prepend() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_prepend(&mut list, variable1).is_some());
    assert!(slist_prepend(&mut list, variable2).is_some());
    assert!(slist_prepend(&mut list, variable3).is_some());
    assert!(slist_prepend(&mut list, variable4).is_some());

    assert_eq!(slist_nth_data(&list, 0), Some(&variable4));
    assert_eq!(slist_nth_data(&list, 1), Some(&variable3));
    assert_eq!(slist_nth_data(&list, 2), Some(&variable2));
    assert_eq!(slist_nth_data(&list, 3), Some(&variable1));

    slist_free(&mut list);
}

#[test]
fn test_slist_free() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    slist_free(&mut list);
    assert!(list.is_none());

    slist_free::<i32>(&mut None);
}

#[test]
fn test_slist_next() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    let mut rover = list.as_ref();
    assert_eq!(rover.map(|n| &n.data), Some(&variable1));
    // 修改为直接比较数据引用
    assert_eq!(slist_nth_data(&list, 0), Some(&variable1));
    rover = rover.and_then(|n| n.next.as_ref());
    assert_eq!(rover.map(|n| &n.data), Some(&variable2));
    rover = rover.and_then(|n| n.next.as_ref());
    assert_eq!(rover.map(|n| &n.data), Some(&variable3));
    rover = rover.and_then(|n| n.next.as_ref());
    assert_eq!(rover.map(|n| &n.data), Some(&variable4));
    rover = rover.and_then(|n| n.next.as_ref());
    assert!(rover.is_none());

    slist_free(&mut list);
}

#[test]
fn test_slist_nth_entry() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    let entry = slist_nth_entry(&list, 0);
    assert_eq!(entry.map(|n| &n.data), Some(&variable1));
    let entry = slist_nth_entry(&list, 1);
    assert_eq!(entry.map(|n| &n.data), Some(&variable2));
    let entry = slist_nth_entry(&list, 2);
    assert_eq!(entry.map(|n| &n.data), Some(&variable3));
    let entry = slist_nth_entry(&list, 3);
    assert_eq!(entry.map(|n| &n.data), Some(&variable4));

    let entry = slist_nth_entry(&list, 4);
    assert!(entry.is_none());
    let entry = slist_nth_entry(&list, 400);
    assert!(entry.is_none());

    slist_free(&mut list);
}

#[test]
fn test_slist_nth_data() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    assert_eq!(slist_nth_data(&list, 0), Some(&variable1));
    assert_eq!(slist_nth_data(&list, 1), Some(&variable2));
    assert_eq!(slist_nth_data(&list, 2), Some(&variable3));
    assert_eq!(slist_nth_data(&list, 3), Some(&variable4));

    assert_eq!(slist_nth_data(&list, 4), None);
    assert_eq!(slist_nth_data(&list, 400), None);

    slist_free(&mut list);
}

#[test]
fn test_slist_length() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    assert_eq!(slist_length(&list), 4);

    assert!(slist_prepend(&mut list, variable1).is_some());
    assert_eq!(slist_length(&list), 5);

    assert_eq!(slist_length::<i32>(&None), 0);

    slist_free(&mut list);
}

#[test]
fn test_slist_remove_entry() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    let entry = slist_nth_entry(&list, 2).unwrap() as *const SListEntry<i32>;
    assert!(slist_remove_entry(&mut list, entry));
    assert_eq!(slist_length(&list), 3);

    let entry = slist_nth_entry(&list, 0).unwrap() as *const SListEntry<i32>;
    assert!(slist_remove_entry(&mut list, entry));
    assert_eq!(slist_length(&list), 2);

    assert!(!slist_remove_entry(&mut list, entry));
    assert!(!slist_remove_entry(&mut list, std::ptr::null()));
    assert!(!slist_remove_entry::<i32>(&mut None, std::ptr::null()));

    slist_free(&mut list);
}

#[test]
fn test_slist_remove_data() {
    let entries = [89, 4, 23, 42, 4, 16, 15, 4, 8, 99, 50, 30, 4];
    let num_entries = entries.len();
    let mut list = None;

    for &entry in entries.iter().rev() {
        assert!(slist_prepend(&mut list, entry).is_some());
    }

    let val = 0;
    assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, &val), 0);
    let val = 56;
    assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, &val), 0);

    let val = 8;
    assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, &val), 1);
    assert_eq!(slist_length(&list), num_entries - 1);

    let val = 4;
    assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, &val), 4);
    assert_eq!(slist_length(&list), num_entries - 5);

    let val = 89;
    assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, &val), 1);
    assert_eq!(slist_length(&list), num_entries - 6);

    slist_free(&mut list);
}

#[test]
fn test_slist_sort() {
    let entries = [89, 4, 23, 42, 4, 16, 15, 4, 8, 99, 50, 30, 4];
    let sorted = [4, 4, 4, 4, 8, 15, 16, 23, 30, 42, 50, 89, 99];
    let num_entries = entries.len();
    let mut list = None;

    for &entry in entries.iter().rev() {
        assert!(slist_prepend(&mut list, entry).is_some());
    }

    slist_sort(&mut list, |a, b| a.cmp(b));

    assert_eq!(slist_length(&list), num_entries);

    for (i, &expected) in sorted.iter().enumerate() {
        let value = slist_nth_data(&list, i);
        assert_eq!(value, Some(&expected));
    }

    slist_free(&mut list);

    let mut empty_list = None;
    slist_sort(&mut empty_list, |a: &i32, b| (*a).cmp(b).into());
    assert!(empty_list.is_none());
}

#[test]
fn test_slist_find_data() {
    let entries = [89, 23, 42, 16, 15, 4, 8, 99, 50, 30];
    let num_entries = entries.len();
    let mut list = None;

    for &entry in entries.iter() {
        assert!(slist_append(&mut list, entry).is_some());
    }

    for &entry in entries.iter() {
        let result = slist_find_data(&list, |a, b| (*a == *b) as i32, &entry);
        assert!(result.is_some());
        assert_eq!(result.map(|n| &n.data), Some(&entry));
    }

    let val = 0;
    assert!(slist_find_data(&list, |a, b| (*a == *b) as i32, &val).is_none());
    let val = 56;
    assert!(slist_find_data(&list, |a, b| (*a == *b) as i32, &val).is_none());

    slist_free(&mut list);
}

#[test]
fn test_slist_to_array() {
    let mut list = None;
    let variable1 = 50;
    let variable2 = 0;
    let variable3 = 0;
    let variable4 = 0;

    assert!(slist_append(&mut list, variable1).is_some());
    assert!(slist_append(&mut list, variable2).is_some());
    assert!(slist_append(&mut list, variable3).is_some());
    assert!(slist_append(&mut list, variable4).is_some());

    let array = slist_to_array(&list);
    assert_eq!(array, vec![variable1, variable2, variable3, variable4]);

    slist_free(&mut list);
}

#[test]
fn test_slist_iterate() {
    let mut list = None;
    let a = 0;

    for _ in 0..50 {
        assert!(slist_prepend(&mut list, a).is_some());
    }

    let mut iter = SListIterator::new(&mut list);
    let mut counter = 0;

    unsafe {
        iter.remove_current();

        while iter.has_more() {
            let data = iter.next();
            assert!(data.is_some());
            counter += 1;

            if counter % 2 == 0 {
                iter.remove();
                iter.remove();
            }
        }

        assert!(iter.next().is_none());
        iter.remove();
    }

    assert_eq!(counter, 50);
    assert_eq!(slist_length(&list), 25);

    slist_free(&mut list);

    let mut empty_list: Option<Box<SListEntry<i32>>> = None;
    let mut iter = SListIterator::new(&mut empty_list);
    let mut counter = 0;

    unsafe {
        while iter.has_more() {
            let data = iter.next();
            assert!(data.is_some());
            counter += 1;

            if counter % 2 == 0 {
                iter.remove();
            }
        }
    }

    assert_eq!(counter, 0);
}

#[test]
fn test_slist_iterate_bad_remove() {
    let mut list = None;
    let mut values = [0; 49];

    for i in 0..49 {
        values[i] = i;
        assert!(slist_prepend(&mut list, values[i]).is_some());
    }

    let mut iter = SListIterator::new(&mut list);

    unsafe {
        while iter.has_more() {
            let val = iter.next().unwrap();

            if *val % 2 == 0 {
                assert_eq!(slist_remove_data(&mut list, |a, b| (*a == *b) as i32, val), 1);
                iter.remove();
            }
        }
    }

    slist_free(&mut list);
}